var Lust69 = function( map ) {

	this.lust = function( x, y ) {
		return this.lusty( this.getMap().mapCoord( y ), this.getMap().mapCoord( x ) );
	};

	this.lusty = function( i, j ) {
		return this.getMap().isInBounds( i, j ) ? this.getCells()[ i ][ j ] : 0;
	};

	this.clear = function() {
		var w = this.getCells()[ 0 ].length;
		var h = this.getCells().length;
		for ( var i = 0 ; i < h ; i++ ) {
			for ( var j = 0 ; j < w ; j++ ) {
				this.getCells()[ i ][ j ] = 0;
			}
		}
	};

	this.force = function( x, y ) {
		//this.distantForce( x, y );
		this.paintingForce( x, y );
	};

	this.fadeForce = function( x, y )  {
		var w = this.getCells()[ 0 ].length;
		var h = this.getCells().length;

		var ii = this.getMap().mapCoord( y );
		var jj = this.getMap().mapCoord( x );

		for ( var x = 0 ; x < 20 ; x++ ) {
			this.getCells()[ ii ][ jj ] = 1000;
			this.fade();
		}
	};

	this.paintingForce = function( x, y ) {
		var w = this.getCells()[ 0 ].length;
		var h = this.getCells().length;

		var i = this.getMap().mapCoord( y );
		var j = this.getMap().mapCoord( x );

		this.clear();

		var value = 1024;
		var honeyDo = [ {i:i,j:j,n:1024} ];
		while ( 0 != honeyDo.length ) {
			var nuTodo = [];
			for ( var i = 0 ; i < honeyDo.length ; i++ ) {

				var todo = honeyDo[ i ];
				if ( this.getMap().clearIJ( todo.i, todo.j ) ) {
					if ( this.getCells()[ todo.i ][ todo.j ] < todo.n ) {
						this.getCells()[ todo.i ][ todo.j ] = todo.n;

						nuTodo.push( {i:todo.i-1,j:todo.j-1,n:todo.n*0.8} );
						nuTodo.push( {i:todo.i-1,j:todo.j-0,n:todo.n*0.8} );
						nuTodo.push( {i:todo.i-1,j:todo.j+1,n:todo.n*0.8} );

						nuTodo.push( {i:todo.i-0,j:todo.j-1,n:todo.n*0.8} );
						//nuTodo.push( {i:todo.i-0,j:todo.j-0,n:todo.n*0.8} );
						nuTodo.push( {i:todo.i-0,j:todo.j+1,n:todo.n*0.8} );

						nuTodo.push( {i:todo.i+1,j:todo.j-1,n:todo.n*0.8} );
						nuTodo.push( {i:todo.i+1,j:todo.j-0,n:todo.n*0.8} );
						nuTodo.push( {i:todo.i+1,j:todo.j+1,n:todo.n*0.8} );
					}
				}
			}
			honeyDo = nuTodo;
		}
	};

	this.distantForce = function( x, y )  {
		var w = this.getCells()[ 0 ].length;
		var h = this.getCells().length;

		var ii = this.getMap().mapCoord( y );
		var jj = this.getMap().mapCoord( x );

		for ( var i = 0 ; i < h ; i++ ) {
			var di = ( i - ii ) * ( i - ii );
			for ( var j = 0 ; j < w ; j++ ) {
				this.getCells()[ i ][ j ] = 1 / (
					1 + di + ( j - jj ) * ( j - jj )
				);
			}
		}
		this.stompMap();
	};

	this.fade = function() { 
		var w = this.getCells()[ 0 ].length;
		var h = this.getCells().length;

		for ( var i = 1 ; i < h-1 ; i++ ) {
			for ( var j = 1 ; j < w-1 ; j++ ) {

				if( !this.getMap().clearIJ( i, j ) ) {
					this.getTmp()[ i ][ j ]  = 0;
					continue;
				}

				var sum = this.getCells()[ i ][ j ];
				var div = 1;

				for ( var ii = i - 1 ; ii < i + 2 ; ii++ ) {

					for ( var jj = j - 1 ; jj < j + 2 ; jj++ ) {
							sum += this.getCells()[ ii ][ jj ];
							div++;
					}
				}
				this.getTmp()[ i ][ j ] = sum / div;
			}
		}
		var tmp = this.getCells();
		this.setCells( this.getTmp() );
		this.setTmp( tmp );
	};

	this.stompMap = function( v ) {
		if ( !v ) v = 0;
		for ( var i = 0 ; i < this.getMap().getH() ; i++ ) {
			for ( var j = 0 ; j < this.getMap().getW() ; j++ ) {
				if ( !this.getMap().clearIJ( i, j ) ) {
					this.getCells()[ i ][ j ] = v;
				}
			}
		}
	};

	this.scale = function() {
		var max = 1;
		for ( var i = 0 ; i < this.getMap().getH() ; i++ ) {
			for ( var j = 0 ; j < this.getMap().getW() ; j++ ) {
				if ( this.getCells()[ i ][ j ] > max ) {
					max = this.getCells()[ i ][ j ];
				}
			}
		}
		for ( var i = 0 ; i < this.getMap().getH() ; i++ ) {
			for ( var j = 0 ; j < this.getMap().getW() ; j++ ) {
				this.getCells()[ i ][ j ] /= max;
			}
		}
	};

	/* ... */

	this.setMap = function( map ) {
		this.map_ = map;
	};

	this.getMap = function() {
		return this.map_;
	};

	this.setCells = function( cells ) {
		this.cells_ = cells;
	};

	this.getCells = function() {
		return this.cells_;
	};

	this.setTmp = function( tmp ) {
		this.tmp_ = tmp;
	};

	this.getTmp = function() {
		return this.tmp_;
	};

	this.toString = function() {
		var s = '<div>';
		for ( var i = 0 ; i < this.getCells().length ; i++ ) {
			s += '<div>';
			for ( var j = 0 ; j < this.getCells()[ i ].length ; j++ ) {
				var n = Math.floor( 255 * this.getCells()[ i ][ j ] );
				var t = 'rgb('+n+','+n+','+n+')';
				if ( 0 == this.getCells()[ i ][ j ]  ) t = '#000044';
				s += '<span style="background:' + t + ';color:' + t + '">_</span>';
			}
			s += '</div>\n';
		}
		return s + '</div>';
	};

	this.init = function( map ) {
		this.setMap( map );
		this.setCells( [] );
		this.setTmp( [] );
		for ( var i = 0 ; i < this.getMap().getH() ; i++ ) {
			var row = [];
			var tmp_row = [];
			for ( var j = 0 ; j < this.getMap().getW() ; j++ ) {
				row.push( 0 );
				tmp_row.push( 0 );
			}
			this.getCells().push( row );
			this.getTmp().push( tmp_row );
		}
	};

	this.init( map );

	//..............

	this.isGoodPosition = function( x, y ) {
		return this.getMap().clear( x, y );
	};

	this.desire = function( gx, gy, sprite ) {
		var ii = this.getMap().mapCoord( gy );
		var jj = this.getMap().mapCoord( gx );
		var max = 0;
		var at = false;

		// backtracking is boring...
		this.getCells()[ ii ][ jj ] *= 0.9;

		for ( var i = -1 ; i < 2 ; i++ ) {
			for ( var j = -1 ; j < 2 ; j++ ) {
				if ( 0 == i && 0 == j ) continue;
				if ( 0 == i || 0 == j ) {
					var lust = this.lusty( ii + i, jj + j );
					if ( lust > max ) {
						max = lust;
						at = {i:i,j:j};
					}
				}
			}
		}
		if ( at ) {
			// TODO: don't be a slack bastard
			if ( -1 == at.i ) sprite.setCurrentDirectionByName( 'up' ); else
			if (  1 == at.i ) sprite.setCurrentDirectionByName( 'down' ); else
			if ( -1 == at.j ) sprite.setCurrentDirectionByName( 'left' ); else
			if (  1 == at.j ) sprite.setCurrentDirectionByName( 'right' ); 
		}
	};

	this.stepSprite = function( sprite, goal ) {
		var gx = sprite.getPosition().getX();
		var gy = sprite.getPosition().getY();

		var i = this.getMap().mapCoord( gy );
		var j = this.getMap().mapCoord( gx );
		if ( goal ) {
			var a = this.getMap().mapCoord( goal.x );
			var b = this.getMap().mapCoord( goal.y );
			if ( i == a && j == b ) {
				return;
			}
		}

		this.desire( gx, gy, sprite );

		sprite.move();

		var x = sprite.getPosition().getX();
		var y = sprite.getPosition().getY();
		i = this.getMap().mapCoord( y );
		j = this.getMap().mapCoord( x );

		if ( !this.isGoodPosition( x, y ) ) {
			this.getCells()[ i ][ j ] *= 0.97;
			this.moveTo( gx, gy );
			sprite.setPosition( new Point2d( gx, gy ) );
			sprite.moveNodeTo( gx, gy );
			x = gx;
			y = gy;
		}
	};

};
